import UIKit
import SnapKit
import WCDBSwift
import AVFoundation
import SwiftyJSON
//import TZImagePickerController
import ZYImagePickerAndBrower
import MJRefresh
import UniformTypeIdentifiers

private let delayTime = 1.2

//todo 常量位置重新放
private let kNOTextKeyboardHeight: CGFloat = 216.0
fileprivate let keyboardChangeFrameTime = 0.25
fileprivate let keyboardHeight = 220

class ChatVC: ChatBaseController {
    let msgService = MessageService()
    
    var shownCell:IndexPath? {
        didSet {
            if oldValue == shownCell {
                return
            }
            let oldCell = self.tableview.cellForRow(at: oldValue ?? IndexPath(row: 0, section: 0)) as? ChatBaseCell
            oldCell?.transitionToHide()
            let newCell = self.tableview.cellForRow(at: shownCell!) as? ChatBaseCell
            newCell?.transitionToShow()
        }
    }
    
    lazy var imgPickerVC: ZYPhotoNavigationViewController = {
        ZYPhotoAlbumSkinColor = UIColor.green
        var controller = ZYPhotoNavigationViewController(photoAlbumDelegate: self, photoAlbumType: .selectPhoto)
        controller.maxSelectCount = 9
        return controller
    }()
    
    lazy var tableview: UITableView = {
        let tableview = UITableView.init()
        tableview.register(UINib(nibName: "ChatPuretextCell",bundle: nil), forCellReuseIdentifier: "ChatPuretextCell")
        tableview.register(UINib(nibName: "ChatNoticecell",bundle: nil), forCellReuseIdentifier: "ChatNoticecell")
        tableview.register(UINib(nibName: "ChatPurevoiceLeftcell",bundle: nil), forCellReuseIdentifier: "ChatPurevoiceLeftcell")
        tableview.register(UINib(nibName: "ChatPureRightCell",bundle: nil), forCellReuseIdentifier: "ChatPureRightCell")
        tableview.register(UINib(nibName: "ChatPurevoiceRightcell",bundle: nil), forCellReuseIdentifier: "ChatPurevoiceRightcell")
        tableview.register(UINib(nibName: "ChatfileLeftcell",bundle: nil), forCellReuseIdentifier: "ChatfileLeftcell")
        tableview.register(UINib(nibName: "ChatfileRightcell",bundle: nil), forCellReuseIdentifier: "ChatfileRightcell")
        tableview.register(UINib(nibName: "ChatpicLeftcell",bundle: nil), forCellReuseIdentifier: "ChatpicLeftcell")
        tableview.register(UINib(nibName: "ChatpicRightcell",bundle: nil), forCellReuseIdentifier: "ChatpicRightcell")
        tableview.register(UINib(nibName: "ChatVideoLeftCell",bundle: nil), forCellReuseIdentifier: "ChatVideoLeftCell")
        tableview.register(UINib(nibName: "ChatVideoRightCell",bundle: nil), forCellReuseIdentifier: "ChatVideoRightCell")
        tableview.dataSource = self
        tableview.delegate = self
        tableview.separatorStyle = UITableViewCell.SeparatorStyle.none
        tableview.estimatedRowHeight = 200
        //tableview上，滑动时，textfiled收起键盘
        tableview.keyboardDismissMode = UIScrollView.KeyboardDismissMode.onDrag
        tableview.backgroundColor = UIColor(named: "chat_bg")
        let fresher = MJRefreshNormalHeader()
        fresher.lastUpdatedTimeLabel.isHidden = true
        fresher.arrowView.isHidden = true
        fresher.stateLabel.isHidden = true
        fresher.setRefreshingTarget(self, refreshingAction: #selector(refresh))
        tableview.mj_header = fresher
        return tableview
    }()
    
    lazy var bottomview: UIView = {
        let bottomview = UIView()
        bottomview.backgroundColor = UIColor(named: "chat_input_bg")
        return bottomview
    }()
    
    //iphonex 底部留白
    lazy var bottomSPaceView: UIView = {
        let bottomview = UIView.init()
        bottomview.backgroundColor = UIColor(named: "chat_input_bg")
        return bottomview
    }()
    
    lazy var inputSectionView:InputSectionView = {
        let input = InputSectionView()
        input.keyboardType = self.keyboardType
        input.delegate = self
        input.msgSendInterval = true
        input.roleisAdminOrSelf = true
        return input
    }()
    
    lazy var keyboardView:UIView = { [unowned self] in
        let view = UIView()
        return view
    }()
    
    lazy var moreView: ChatMoreView = { [unowned self] in
        let moreV = ChatMoreView()
        moreV.delegate = self
        moreV.alpha = 0
        return moreV
    }()
    
    // MARK: 表情面板
    lazy var emotionView: LXFChatEmotionView = { [unowned self] in
        let emotionV = LXFChatEmotionView()
        emotionV.delegate = self
        return emotionV
    }()
    
    // MARK: 录音视图
    lazy var voiceSectionView: VoiceSectionView = {
        let recordVoiceV = VoiceSectionView()
        recordVoiceV.isHidden = true
        return recordVoiceV
    }()
    
    //属性======================================
    var finishRecordingVoice: Bool = true   // 决定是否停止录音还是取消录音
    var data = [ChatMessage]()
    lazy var keyboardType:PropertyObservable<KeyboardType> = {
        let keyboard = PropertyObservable<KeyboardType>()
        keyboard.value = .text
        keyboard.after = { type in
            UIView.animate(withDuration: keyboardChangeFrameTime) {
                self.view.layoutIfNeeded()
                if let keyboardType = type,keyboardType != .noting {
                    if self.data.count > 0 {
                        self.tableview.scrollToRow(at: IndexPath(row: self.data.count - 1, section: 0), at: .bottom, animated: false)
                    }
                }
            }
        }
        return keyboard
    }()
    
    lazy var detailBarItem: UIBarButtonItem = {
        let detailBarItem = UIBarButtonItem(image: #imageLiteral(resourceName:"barbuttonicon_InfoSingle"), style: .plain, target: self, action: #selector(detailBtnClick))
        return detailBarItem
    }()
    
    var chatType:ChatType!
    var sessionServerId:Int = 0
    var sessionName:String = "聊天"
    //  var role:ChatRoomMemberRole = .admin
    var time = Date().timeIntervalSince1970
    let pageSize:Int = 20
    var head = false
    
    let service = ChatService()
    
    override func viewWillAppear(_ animated: Bool) {
        //    self.checkIsFounder()
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        self.navigationItem.title = self.sessionName
        if chatType == ChatType.group  {
            self.navigationItem.rightBarButtonItem = self.detailBarItem
            self.detailBarItem.image = #imageLiteral(resourceName:"barbuttonicon_InfoGroup")
            self.inputSectionView.enableAt = true
        }
        
        self.setUI()
        self.setupNotifications()
        self.bindObserver()
        setEmotionIninputview()
        AudioRecordUtils.instance.delegate = self
        
        let count = self.loadData()
        if count > 0 {
            DispatchQueue.main.async {
                // 主线程中
                self.tableview.scrollToRow(at: IndexPath(row: count - 1, section: 0), at: .bottom, animated: false)
            }
        }
    }
    
    
    override func viewDidDisappear(_ animated: Bool) {
        super.viewDidDisappear(animated)
        if let nvc = self.navigationController {
            if !nvc.viewControllers.contains(self) {
                NotificationCenter.default.removeObserver(self)
            }
        }else {
            NotificationCenter.default.removeObserver(self)
        }
    }
    
    func setUI(){
        //        self.edgesForExtendedLayout = UIRectEdge(rawValue: 0)
        
        self.inputSectionView.voiceButton.isEnabled = true
        self.inputSectionView.moreButton.isEnabled = true
        self.inputSectionView.emotionButton.isEnabled = true
        
        
        self.emotionView.alpha = 0
        
        
        //        self.view.backgroundColor = .secondarySystemBackground
        self.view.backgroundColor = UIColor(named: "chat_bg")
        self.view.addSubview(tableview)
        self.view.bringSubviewToFront(tableview)
        self.view.addSubview(bottomview)
        self.bottomview.addSubview(inputSectionView)
        self.bottomview.addSubview(keyboardView)
        self.keyboardView.addSubview(moreView)
        self.keyboardView.addSubview(emotionView)
        self.view.addSubview(voiceSectionView)
        self.view.addSubview(bottomSPaceView)
        
        tableview.snp.makeConstraints { (make) in
            make.left.right.top.equalToSuperview()
            make.bottom.equalTo(bottomview.snp.top)
        }
        
        voiceSectionView.snp.makeConstraints { make in
            make.edges.equalTo(self.tableview)
        }
        
        bottomview.snp.makeConstraints { (make) in
            make.left.right.equalToSuperview()
            make.top.equalTo(self.inputSectionView.snp.top)
            if #available(iOS 11, *) {
                make.bottom.equalTo(self.view.safeAreaLayoutGuide)
            } else {
                make.bottom.equalToSuperview()
            }
        }
        
        bottomSPaceView.snp.makeConstraints { (make) in
            make.left.right.equalToSuperview()
            make.top.equalTo(bottomview.snp.bottom)
            if #available(iOS 11, *) {
                make.bottom.equalToSuperview()
            } else {
                make.bottom.equalToSuperview().offset(-34)
            }
        }
        
        inputSectionView.snp.makeConstraints { (make) in
            make.left.right.equalToSuperview()
            make.bottom.equalTo(self.keyboardView.snp.top)
        }
        
        keyboardView.snp.makeConstraints { make in
            make.left.right.bottom.equalToSuperview()
            make.height.equalTo(0)
        }
        
        moreView.snp.makeConstraints { make in
            make.top.equalToSuperview()
            make.height.equalTo(keyboardHeight)
            make.left.right.equalToSuperview()
        }
        
        emotionView.snp.makeConstraints { make in
            make.top.equalToSuperview()
            make.height.equalTo(keyboardHeight)
            make.left.right.equalToSuperview()
        }
    }
    
    func loadData() -> Int {
        if self.head {
            return 0
        }
        let msgs = msgService.getMessages(sessionServerId: self.sessionServerId, chatType: self.chatType,date:Date(timeIntervalSince1970: self.time), pageSize: self.pageSize)
        if msgs.count == 0 {
            self.head = true
            return 0
        }
        self.time = msgs[0].ts
        self.data = msgs + self.data
        let count = msgs.count
        msgService.readMsgs(sessionServerId: self.sessionServerId)
        return count
    }
    
    func setEmotionIninputview() {
        
    }
    
    private func bindObserver() {
        keyboardView.bind(keyboardType, handler: { type in
            if let tp = type {
                switch tp {
                case .more:
                    self.keyboardView.snp.updateConstraints { make in
                        make.height.equalTo(keyboardHeight)
                    }
                case .emotion:
                    self.keyboardView.snp.updateConstraints { make in
                        make.height.equalTo(keyboardHeight)
                    }
                default:
                    self.keyboardView.snp.updateConstraints { make in
                        make.height.equalTo(0)
                    }
                }
            }
        })
        
        moreView.bind(keyboardType, handler: { type in
            if let tp = type {
                switch tp {
                case .more:
                    UIView.animate(withDuration: keyboardChangeFrameTime) {
                        self.moreView.alpha=1
                    }
                default:
                    UIView.animate(withDuration: keyboardChangeFrameTime) {
                        self.moreView.alpha=0
                    }
                }
            }
        })
        
        emotionView.bind(keyboardType, handler: { type in
            if let tp = type {
                switch tp {
                case .emotion:
                    UIView.animate(withDuration: keyboardChangeFrameTime) {
                        self.emotionView.alpha=1
                        self.bottomSPaceView.backgroundColor = UIColor(named: "chat_input_bg")
                    }
                default:
                    UIView.animate(withDuration: keyboardChangeFrameTime) {
                        self.emotionView.alpha=0
                        self.bottomSPaceView.backgroundColor = UIColor(named: "chat_input_bg")
                    }
                }
            }
        })
        
        inputSectionView.bind(keyboardType,handler: {type in
            if let tp = type {
                switch tp {
                case .voice:
                    self.inputSectionView.snp.remakeConstraints { make in
                        make.left.equalTo(self.view)
                        make.right.equalTo(self.view)
                        make.bottom.equalTo(self.keyboardView.snp.top)
                        make.top.equalTo(self.inputSectionView.recordButton.snp.top).offset(0-self.inputSectionView.margin)
                    }
                case .text:
                    self.inputSectionView.snp.remakeConstraints { make in
                        make.left.equalTo(self.view)
                        make.right.equalTo(self.view)
                        make.bottom.equalTo(self.keyboardView.snp.top)
                        make.top.equalTo(self.inputSectionView.textView.snp.top).offset(0-self.inputSectionView.margin)
                    }
                default:
                    self.inputSectionView.snp.remakeConstraints { make in
                        make.left.equalTo(self.view)
                        make.right.equalTo(self.view)
                        make.bottom.equalTo(self.keyboardView.snp.top)
                        make.top.equalTo(self.inputSectionView.textView.snp.top).offset(0-self.inputSectionView.margin)
                    }
                    self.inputSectionView.resignInputSection()
                }
            }
        })
        
    }
    
    private func setupNotifications() {
        //添加距离感应
        NotificationCenter.default.addObserver(self, selector: #selector(deviceProximityStateDidChange(_:)), name: NSNotification.Name(rawValue: proximityStateDidChange), object: nil)  //红外感应变化
        
        //录音按钮长按开始
        NotificationCenter.default.addObserver(self, selector: #selector(chatBarRecordBtnLongTapBegan(_:)), name: NSNotification.Name(rawValue: recordBtnLongTapBegan), object: nil)
        //录音按钮长按改变
        NotificationCenter.default.addObserver(self, selector: #selector(chatBarRecordBtnLongTapChanged(_:)), name: NSNotification.Name(rawValue: recordBtnLongTapChanged), object: nil)
        //录音按钮长按结束
        NotificationCenter.default.addObserver(self, selector: #selector(chatBarRecordBtnLongTapEnded(_:)), name: NSNotification.Name(rawValue: recordBtnLongTapEnded), object: nil)
        
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil)
        
        NotificationCenter.default.addObserver(self, selector: #selector(onNewMsg), name: NSNotification.Name(rawValue: newMsg), object: nil)
        
        
        NotificationCenter.default.addObserver(self, selector: #selector(onStatusChange), name: connectionStatusChange, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(selectedMembers), name: NSNotification.Name(rawValue: remindedGroupMem), object: nil)

        
    }
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        self.view.endEditing(true)
    }
    
    // 收起键盘
    func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
        self.view.endEditing(true)
        keyboardType.value = .noting
        inputSectionView.resignInputSection()
    }
    
}

//MARK: UITableViewDataSource,UITableViewDelegate
extension ChatVC: UITableViewDataSource, UITableViewDelegate{
    // datasource
    internal func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let msg = self.data[indexPath.row]
        var cellId = ""
        switch (msg.messageType,msg.isMe) {
        case (.text,true):
            cellId = "ChatPureRightCell"
        case (.text,false):
            cellId = "ChatPuretextCell"
        case (.audio,true):
            cellId = "ChatPurevoiceRightcell"
        case (.audio,false):
            cellId = "ChatPurevoiceLeftcell"
        case (.video,true):
            cellId = "ChatVideoRightCell"
        case (.video,false):
            cellId = "ChatVideoLeftCell"
        case (.img,true):
            cellId = "ChatpicRightcell"
        case (.img,false):
            cellId = "ChatpicLeftcell"
        case (.file,true):
            cellId = "ChatfileRightcell"
        case (.file,false):
            cellId = "ChatfileLeftcell"
        case (.notice,true):
            cellId = "ChatNoticecell"
        case (.notice,false):
            cellId = "ChatNoticecell"
        default:
            cellId = "ChatPuretextCell"
        }
        if indexPath.row <= 0 {
            msg.showTimeLabel = true
        } else {
            let preMsg = self.data[indexPath.row-1]
            if TimeUtil.instance.isGreatThan(a: msg.ts, b: preMsg.ts, difference: 60 * 5) {
                msg.showTimeLabel = true
            }
        }
        let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath) as! ChatBaseCell
        cell.delegate = self
        cell.backgroundColor = .clear
        cell.setup(model: msg)
        
        if indexPath.row == self.data.count-1 {
            self.shownCell = indexPath
            cell.transitionToShow()
        } else {
            cell.transitionToHide()
        }
        return cell
    }
    
    // delegate
    func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        return 1
    }
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return self.data.count
    }
    
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        self.view.endEditing(true)
        keyboardType.value = .noting
        inputSectionView.resignInputSection()
        self.shownCell = indexPath
    }
    
    //    func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? {
    //        self.shownCell = indexPath
    //    }
}



extension ChatVC {
    @objc func refresh(sender: AnyObject) {
        DispatchQueue.global().asyncAfter(deadline: .now() + 0.1) {
            let count = self.loadData()
            DispatchQueue.main.async {
                self.tableview.mj_header.endRefreshing()
                if count > 0 {
                    self.tableview.reloadData()
                    self.tableview.scrollToRow(at: IndexPath(row: count, section: 0), at: .top, animated: false)
                }
            }
        }
    }
    
    @objc func detailBtnClick() {
        let groupDetailController = GroupDetailController()
        groupDetailController.groupId = self.sessionServerId
        self.navigationController?.pushViewController(groupDetailController, animated: true)
    }
    
    /** 键盘弹出*/
    @objc func keyboardWillShow(notification: Notification) {
        if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue.size {
            inputSectionWillChangeHeight(heightOffset: keyboardSize.height)
        }
        keyboardType.value = .text
    }
    
    /* 键盘隐藏*/
    @objc func keyboardWillHide(notification: Notification) {
        if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.size {
            inputSectionWillChangeHeight(heightOffset: 0 - keyboardSize.height)
        }
    }
    
    /* ============== 红外感应 有物体靠近 ============= */
    @objc func deviceProximityStateDidChange (_ note: Notification) {
        do {
            if UIDevice.current.proximityState { //当靠近听筒
                try AVAudioSession.sharedInstance().setCategory(AVAudioSession.Category.playAndRecord)
            } else {
                try AVAudioSession.sharedInstance().setCategory(AVAudioSession.Category.playback)
            }
        } catch {
            print(error)
        }
    }
    
    /* ============================== 录音按钮长按事件 ============================== */
    @objc func chatBarRecordBtnLongTapBegan(_ note: Notification) {
        //        if !AudioRecordUtils.instance.isHasPermission() {
        //            noAudioPermission()
        //            return
        //        }
        //        print("长按开始")
        finishRecordingVoice = true
        voiceSectionView.recording()
        //        // 开始录音
        DispatchQueue.global().async {
            AudioRecordUtils.instance.beginRecord(duration: 60)
        }
        //        LXFWeChatTools.shared.recordVoice()
    }
    
    @objc func chatBarRecordBtnLongTapChanged(_ note: Notification) {
        // LXFLog("长按平移")
        //        print("长按平移")
        let longTap = note.object as! UILongPressGestureRecognizer
        let point = longTap.location(in: self.inputSectionView)
        if inputSectionView.point(inside: point, with: nil) {
            voiceSectionView.recording()
            finishRecordingVoice = true
        } else {
            voiceSectionView.slideToCancelRecord()
            finishRecordingVoice = false
        }
    }
    
    @objc func chatBarRecordBtnLongTapEnded(_ note: Notification) {
        voiceSectionView.hide()
        if finishRecordingVoice {
            //            // 停止录音
            AudioRecordUtils.instance.stopRecord()
        } else {
            //            // 取消录音
            AudioRecordUtils.instance.cancelRecord()
        }
    }
    
    @objc func onNewMsg(_ note: Notification) {
        if let data = note.userInfo {
            //            let data = notification.userInfo as! Dictionary<String, Any>
            let messageArray = data["list"] as! [Dictionary<String, Any>]
            if (messageArray.count == 0) {
                return
            }
            DispatchQueue.global().async {
                self.newMsgArrived(messageArray)
            }
        }
    }
    
    func newMsgArrived(_ array: [Dictionary<String, Any>]) {
        do {
            let db = SQLiteHelper.getDb()
            for msg in array {
                print(msg)
                if sessionServerId == msg["sessionServerId"] as! Int {
                    let msgType = MessageType(rawValue: msg["messageType"] as! Int)
                    let userId = msg["userId"] as! Int
                    let userName = msg["name"] as? String ?? "\(userId)"
                    let audioRead = msg["audioRead"] as! Bool
                    let contact = try ContactDao.getContact(userId)
                    let groupMember = try GroupDao.getMember(self.sessionServerId, userId: userId)
                    let name = contact?.remarkName ?? groupMember?.nickName ?? contact?.name ?? userName
                    let newMsg = ChatMessage(sessionId: sessionServerId, from: userId, fromName: name, me: msg["me"] as! Int,messageType: msgType ?? MessageType.unknown)
                    newMsg.ts = msg["ts"] as! TimeInterval
                    newMsg.avatar = msg["avatar"] as? String
                    newMsg.text = msg["messageContent"] as? String
                    newMsg.localId = msg["id"] as? Int
                    newMsg.status = .success
                    newMsg.chatType = chatType
                    switch newMsg.messageType {
                    case .audio:
                        let ss = newMsg.text!.split(separator: "|")
                        newMsg.audioPath = String(ss[0])
                        newMsg.audioDuration = Double(String(ss[1]))
                        newMsg.read = audioRead
                        break
                    case .img:
                        let json = JSON.init(parseJSON: newMsg.text ?? "")
                        newMsg.imgFileName = json["fileName"].stringValue
                        newMsg.memSize = json["size"].intValue
                        newMsg.imgData = Data(base64Encoded: json["data"].stringValue, options: Data.Base64DecodingOptions(rawValue: 0))
                        let width = json["width"].doubleValue
                        let height = json["height"].doubleValue
                        newMsg.imgSize = CGSize(width: width, height: height)
                    case .notice:
                        let text = NoticeHandlerFactory.instance.getHandler(newMsg).show(newMsg)
                        newMsg.text = text
                        newMsg.messageType = .notice
                    case .file:
                        let json = JSON.init(parseJSON: newMsg.text ?? "")
                        newMsg.fileName = json["name"].stringValue
                        newMsg.ext = json["ext"].stringValue
                        newMsg.fileSize = json["size"].intValue
                        newMsg.storeFile = json["remote"].stringValue
                        break
                    case .video:
                        let json = JSON.init(parseJSON: newMsg.text ?? "")
                        newMsg.videoName = json["fileName"].stringValue
                        newMsg.videoWidth = CGFloat(json["width"].int64Value)
                        newMsg.videoHeight = CGFloat(json["height"].int64Value)
                        newMsg.videoDuration = json["duration"].int64Value
                        newMsg.videoName = json["fileName"].stringValue
                        newMsg.videoSize = json["size"].int64Value
                    case .sticker:
                        let json = JSON.init(parseJSON: newMsg.text ?? "")
                        newMsg.stickerPath = json["sticker"].rawString()
                        newMsg.stickerName = json["name"].rawString()
                        newMsg.category = String(json["category"].int64Value)
                    case .unknown:
                        newMsg.text = "[未知消息类型，请升级app]"
                        newMsg.messageType = .text
                        break
                    default:
                        break
                    }
                    DispatchQueue.main.async {
                        if self.data.count > 0 {
                            //                            let index = IndexPath.init(row: self.data.count - 1, section: 0)
                            //                            self.shownCell = index
                            //                            let cell = self.tableview.cellForRow(at: index) as? ChatBaseCell
                            //                            cell?.transitionToShow()
                        }
                        _ = self.addRow(newMsg)
                        
                    }
                }
            }
            try db.run(transaction: {[unowned self]_ in
                let msgUpd = Message()
                msgUpd.unread = false
                try db.update(table: Message.table, on: Message.CodingKeys.unread, with: msgUpd,where: Message.CodingKeys.sessionServerId == self.sessionServerId && Message.CodingKeys.unread == 1)
            })
        } catch {
            print(error.localizedDescription)
        }
    }
    
}


// MARK:- InputSectionViewDelegate
extension ChatVC: InputSectionViewDelegate {
    func inputSectionChangeHeight(newHeight: CGFloat) {
        UIView.animate(withDuration: keyboardChangeFrameTime) {
            self.tableview.layoutIfNeeded()
            if self.data.count > 0 {
                self.tableview.scrollToRow(at: IndexPath(row: self.data.count - 1, section: 0), at: .bottom, animated: false)
            }
        }
    }
    
    func inputSectionWillChangeHeight(heightOffset: CGFloat) {
        //    let frame = inputSectionView.frame
        
        var offset = heightOffset
        if offset > CGFloat(0) && isFullScreen() {
            offset = offset - 34
        }
        
        keyboardView.snp.updateConstraints() { (make) -> Void in
            make.bottom.equalToSuperview().offset(0 - CGFloat.maximum(CGFloat(0), offset))
        }
        
        //设置键盘弹出和消失页面动画同步顺滑流畅！！消息同步滚动到最底部，如果已经在最底部，类似被键盘推上去的效果
        UIView.animate(withDuration: keyboardChangeFrameTime) {
            self.view.layoutIfNeeded()
        }
    }
    
    func isFullScreen() -> Bool {
        if UIScreen.main.bounds.height >= 812 {
            return true
        }
        
        return false
    }
    
    func sendMessage(sndMsg: ChatMessage) {
        sndMsg.sessionId = self.sessionServerId
        sndMsg.chatType = self.chatType
        DispatchQueue.main.async {
            _ = self.addRow(sndMsg)
            
            DispatchQueue.global().async {
                self.service.sendSingleOrGroupMsg(msg: sndMsg,result: { msg in
                    
                })
            }
            self.inputSectionView.textView.text = ""
        }
        //    }
    }
    
    
    //获取当前时间戳
    func  getNowTimeTimestamp2() -> TimeInterval{
        return Date().timeIntervalSince1970
    }
    
    
    func resendMsg(sndMsg: ChatMessage,indexPath:IndexPath) {
        DispatchQueue.global().async {
            self.service.sendSingleOrGroupMsg(msg: sndMsg,result: { msg in
                DispatchQueue.main.async {
                    self.tableview.reloadRows(at: [indexPath], with: .none)
                }
            })
        }
    }
    
    
    
    func addRow(_ msg: ChatMessage) -> IndexPath{
        UIView.setAnimationsEnabled(false)
        self.data.append(msg)
        let indexPath = IndexPath(row: self.data.count - 1, section: 0)
        self.tableview.beginUpdates()
        self.tableview.insertRows(at: [indexPath], with: .none)
        self.tableview.endUpdates()
        self.tableview.layoutIfNeeded()
        self.tableview.scrollToRow(at: indexPath, at: .top, animated: true)
        UIView.setAnimationsEnabled(true)
        return indexPath
    }
    
    func messageTextTooLong() {
        self.voiceSectionView.messageTextTooLong()
    }
    
    func showAlertMessage() {
    }
    
    func showRemindVC() {
        if chatType == ChatType.group {
            let remindVC = RemindVC()
            remindVC.title = NSLocalizedString("选择提醒的人",comment:"选择提醒的人")
            remindVC.groupId = self.sessionServerId
            let nav = UINavigationController(rootViewController: remindVC)
            // ios 15以上添加半屏展示
            if #available(iOS 15.0, *),let sheet = nav.sheetPresentationController {
                sheet.detents = [.medium(), .large()]
            }
            self.present(nav, animated: true, completion: nil)
            self.inputSectionView.textView.text = self.inputSectionView.textView.text + "@"
        }
    }
    
}


//MARK:- ChatCellDelegate
extension ChatVC:ChatCellDelegate {
    func deleteDelegate(msg: ChatMessage) {
        let arr = self.data as NSArray
        let index = arr.index(of: msg)
        self.data.remove(at: index)
        let service = MessageService()
        service.deleteMsg(msg: msg)
        
        self.tableview.deleteRows(at: [IndexPath(row: index, section: 0)], with: .left)
    }
    
    func reportDelegate(msg: ChatMessage) {
        
    }
    
    func zhuanfaDelegate(msg: ChatMessage) {
        let zfchooseVC = TstZfChooseSessionVC()
        zfchooseVC.msg = msg
        zfchooseVC.superServerID = self.sessionServerId
        zfchooseVC.title = NSLocalizedString("选择一个聊天",comment:"选择一个聊天")
        let nav = UINavigationController.init(rootViewController: zfchooseVC)
        self.present(nav, animated: true, completion: nil)
    }
    
    func addToFavouriteEmotions(msg: ChatMessage) {
        
    }
    
    func playAndRecordDelegate(msg: ChatMessage) {
        
    }
    
    func playBackDelegate(msg: ChatMessage) {
        
    }
    
    func openEmotion(_ param: [String : Any]) {
        
    }
    
    func playVideo(url: NSURL) {
        
    }
    
    func openRedPacket(msg: ChatMessage) {
        
    }
    
    //长按头像在textview 中添加@
    func addAtInTextviewDelegate(msg: ChatMessage) {
        if self.chatType != .group {
            return
        }
        let groupService = GroupService()
        guard let member = groupService.getGroupMember(sessionServerId,memberId:msg.from) else {
            return
        }
        NotificationCenter.default.post(name: NSNotification.Name(remindedGroupMem), object: self, userInfo: ["member":member])
        self.inputSectionView.textView.becomeFirstResponder()
    }
    
    func openWebPage(_ param: Param) {
        let web = ChatRoomWebBrowserController()
        web.param = param
        let back = UIBarButtonItem()
        back.title = "返回"
        self.navigationItem.backBarButtonItem = back
        self.navigationController?.pushViewController(web, animated: true)
    }
    
    func openImg(_ param: [String: Any]) {
        //        var imgMsgs = service.searchImg(fromSession: sessionServerId?.intValue)
        var imgMsgs = [ChatMessage]()
        // 当前图片索引
        var index = 0
        let model = param["model"] as! ChatMessage
        for imgMsg in imgMsgs {
            if imgMsg.imgFileName == model.imgFileName {
                break
            } else {
                index += 1
            }
        }
        // 防止没有同步到本地导致数组越界
        if imgMsgs.count == 0 {
            imgMsgs.append(model)
        }
        
        let indexP = IndexPath(item: index, section: 0)
        let photoBrowserVC = LXFPhotoBrowserController(indexPath: indexP, msgModels: imgMsgs)
        let navphotoBrowserVC = LXFBaseNavigationController(rootViewController: photoBrowserVC)
        navphotoBrowserVC.cc_setZoomTransition(originalView: param["view"] as! UIImageView)
        self.present(navphotoBrowserVC, animated: true, completion: nil)
    }
    
    func resend(_ msg: ChatMessage,cell:UITableViewCell) {
        let indexPath = self.tableview.indexPath(for: cell)!
        msg.status = .pending
        self.tableview.reloadRows(at: [indexPath], with: .none)
        self.resendMsg(sndMsg: msg,indexPath: indexPath)
    }
}

extension ChatVC: ChatMoreViewDelegate {
    func cellOnClick(moreView: ChatMoreView, selectType: ChatMoreType) {
        if selectType == .pic {   // 图片qw
            TGPhotoPickerManager.shared.takePhoto(presentStyle: .automatic,{ config in
                config.tg_type(.wechat)
                config.tg_padding(2)
                config.tg_ascending(true)
                config.tg_colCount(4)
//                config.tg_checkboxType(.circle)
                config.tg_isShowIndicator(true)
                config.tg_selectKind(.all)
                config.tg_checkboxCellWH(30)
            }) { (assets, thumbnails, originImgs, datas) in
                let imgs = originImgs.filter { $0 != nil}.map { $0! }
                
                DispatchQueue.global().async(execute: {
                    imgs.forEach({ (photo) in
                        //                        let photo = model.originImage!
                        if let msg = self.service.compressImg(photo, to: self.sessionServerId) {
                            DispatchQueue.main.async(execute: {
                                self.sendMessage(sndMsg: msg)
                            })
                        }
                    })
                })
            }
        } else if selectType == .file {
            presentFile()
        } else if selectType == .camera {
            let cameraVC = UIImagePickerController()
            cameraVC.sourceType = .camera
//            cameraVC.mediaTypes = [UTType.image.identifier, UTType.movie.identifier]
            cameraVC.delegate = self
            self.present(cameraVC, animated: true, completion: nil)
        }
    }
    
    func presentFile() {
        let vc = UIDocumentPickerViewController(forOpeningContentTypes: [.item], asCopy: true)
        vc.delegate = self
        self.present(vc,animated: true, completion: nil)
    }
}

//MARK: 文件选择
extension ChatVC: UIDocumentPickerDelegate {
    public func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentAt url: URL) {
        do {
            let file = url.lastPathComponent
            let array = file.components(separatedBy: ".")
            let fileName = array.dropLast().joined()
            let ext = array.last ?? ""
            let size = try FileManager.default.attributesOfItem(atPath: url.path)[.size] as! Int / 1024
            let remote = NSUUID().uuidString.replacingOccurrences(of:"-",with: "") + ".\(ext)"
            let obj:[String:Any] = ["name":fileName,"ext":ext,"size":size ,"remote":remote]
            let json = JSON(obj)
            let msgContent = json.rawString()
            
            
            let cacheDir = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask)[0] as URL
            let fileDir = cacheDir.appendingPathComponent("files/", isDirectory: true)
            try FileManager.default.createDirectory(at: fileDir, withIntermediateDirectories: true, attributes: nil)
            let fileUrl = fileDir.appendingPathComponent(remote, isDirectory: false)
            try FileManager.default.moveItem(atPath: url.path, toPath: fileUrl.path )
            
            
            DispatchQueue.main.async(execute: {
                let msg = ChatMessage(sessionId: self.sessionServerId, from: AppStatusManager.instance.userLoginStatus.1!, fromName: AppStatusManager.instance.userLoginStatus.2!,messageType: .file)
                msg.avatar = AppStatusManager.instance.avatar
                msg.fileName = fileName
                msg.storeFile = remote
                msg.text = msgContent
                msg.fileSize = size
                msg.ext = ext
                msg.download = true
                self.sendMessage(sndMsg: msg)
            })
        } catch {
            print("=============发送文件消息报错了")
            self.view.makeToast("发送文件失败", duration: 3.0, position: .center)
        }
    }
    
}


//MARK:- AudioRecordDelegate
extension ChatVC: AudioRecordDelegate {
    func recordBegin() {
        print("begin record")
    }
    
    func recordEnd(recordPath: String,fileName:String, seconds: Double) {
        let msg = ChatMessage(sessionId: sessionServerId, from: AppStatusManager.instance.userLoginStatus.1! , fromName: AppStatusManager.instance.userLoginStatus.2!, messageType: .audio)
        msg.audioPath = fileName
        msg.audioDuration = seconds
        msg.avatar = AppStatusManager.instance.avatar
        msg.text = "\(fileName)|\(seconds)"
        msg.me = 1
        sendMessage(sndMsg: msg)
    }
    
    func recordCanceled() {
        print("cancel record")
    }
    
    func recordTooShort() {
        voiceSectionView.messageTooShort()
    }
    
    func decibels(decibels: Float) {
        DispatchQueue.main.async() {
            let level = (decibels - (-80)) / 10
            self.voiceSectionView.updateMetersValue(level)
        }
    }
    
    func playBegin(msg:ChatMessage){
        DispatchQueue.main.async {
            UIDevice.current.isProximityMonitoringEnabled = true
        }
        msg.read = true
        msgService.updateMsgReadState(msg:msg)
    }
    
    func playEnd(_ filePath: String) {
        DispatchQueue.main.async {
            UIDevice.current.isProximityMonitoringEnabled = false
        }
        NotificationCenter.default.post(name: NSNotification.Name(rawValue: noteChatMsgAudioPlayEnd), object: filePath)
    }
    
    func playInterrupted() {
        DispatchQueue.main.async {
            UIDevice.current.isProximityMonitoringEnabled = false
        }
        NotificationCenter.default.post(name: NSNotification.Name(rawValue: noteChatMsgAudioPlayInterrupted), object: nil)
    }
    
    func noAudioPermission() {
        DispatchQueue.main.async() {
            let alertController = UIAlertController(title: "无法录音",
                                                    message: "请在iPhone的\"设置-隐私-麦克风\"选项中，允许APP访问你的手机麦克风", preferredStyle: .alert)
            let okAction = UIAlertAction(title: "好", style: .default, handler: { action in
                print("ok")
            })
            alertController.addAction(okAction)
            UIApplication.shared.keyWindow?.rootViewController?.present(alertController, animated: true)
        }
    }
}



//MARK:- TZImagePickerControllerDelegate
extension ChatVC: ZYPhotoAlbumProtocol {
    func photoAlbum(selectPhotos: [ZYPhotoModel]) {
        
        DispatchQueue.global().async(execute: {
            selectPhotos.forEach({ (model) in
                let photo = model.originImage!
                if let msg = self.service.compressImg(photo, to: self.sessionServerId) {
                    DispatchQueue.main.async(execute: {
                        self.sendMessage(sndMsg: msg)
                    })
                }
            })
        })
    }
}

extension ChatVC {
    @objc func onStatusChange(note: Notification) {
        guard let data = note.userInfo,let newStatus = data["newStatus"] as? Int,let status = ConnectionStatus(rawValue:newStatus) else {
            return
        }
        DispatchQueue.main.async {
            switch status {
            case .Connecting :
                self.navigationItem.title = "\(self.sessionName)(连接中)"
            case .Login :
                self.navigationItem.title = "\(self.sessionName)(连接中)"
            case .ConnectOK:
                self.navigationItem.title = self.sessionName
            case .LoginOK:
                self.navigationItem.title = self.sessionName
            default:
                //        self.navigationItem.title = "\(self.sessionName)(未连接)"
                self.navigationItem.title = "\(self.sessionName)"
            }
        }
    }
    
    @objc func selectedMembers(noti: Notification) {
        
        let member = noti.userInfo?["member"] as! ChatGroupMember
        let name = member.contact?.name ?? ""
        var text = self.inputSectionView.textView.text!
        var start = self.inputSectionView.textView.attributedText.length
        if text.last == "@" {//如果是通过输入@字符的方式@某一个人,将原有的@字符删除,使用block中的完整字符替代
            start = start - 1
            text = text.substring(s: 0, text.count - 1)
        }
        let atBlock:AtBlock = self.inputSectionView.atModel.addAtMember(key: member.userId, name:name , start: start)
        self.inputSectionView.textView.text = text + atBlock.text
        self.inputSectionView.textView.becomeFirstResponder()
    }
}

//MARK:- LXFChatEmotionViewDelegate 默认表情代理方法
extension ChatVC: LXFChatEmotionViewDelegate {
    
    func chatEmotionViewSend(emotionView: LXFChatEmotionView) {
        
        // 取出字符串
        let message = self.inputSectionView.textView.getEmotionString()
        print("发送图片文本:\(message)")
        let msg = ChatMessage(sessionId: Int(0), from: AppStatusManager.instance.userLoginStatus.1!, fromName: AppStatusManager.instance.userLoginStatus.2!)
        msg.avatar = AppStatusManager.instance.avatar
        msg.text = message
        
        if msg.text?.trimmingCharacters(in: CharacterSet.whitespaces).count == 0 {
            return
        }else {
            sendMessage(sndMsg:msg)
        }
    }
    
    func chatEmotionView(emotionView: LXFChatEmotionView, didSelectedEmotion emotion: LXFChatEmotion) {
        LXFLog(emotion)
        // 插入表情
        self.inputSectionView.textView.insertEmotion(emotion: emotion)
    }
}

extension ChatVC: UIImagePickerControllerDelegate,UINavigationControllerDelegate {
    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
        let mediaType = info[UIImagePickerController.InfoKey.mediaType] as! String
        switch mediaType {
        case "public.image":
            let originalImage = info[UIImagePickerController.InfoKey.originalImage] as! UIImage
            
            // 在此处处理选择的照片
            if let msg = self.service.compressImg(originalImage, to: self.sessionServerId) {
                DispatchQueue.main.async(execute: {
                    self.sendMessage(sndMsg: msg)
                })
            }
            
        case "public.movie":
            print("Selected media is video")
            let videoUrl = info[UIImagePickerController.InfoKey.mediaURL] as! URL
            //1. 获取文件名
            let videoFileName = VideoUtil.instance.createVideoName(videoUrl: videoUrl.absoluteString)
            
            DispatchQueue.global().async {
                // 2.获取到自己指定文件夹地址 file/.../documents/....
                let fm = FileManager.default
                let urlForDocument = fm.urls(for: .documentDirectory, in: .userDomainMask)[0] as URL
                let urlForVideoUrl = urlForDocument.appendingPathComponent("videoUrl", isDirectory: true)
                do {
                    try FileManager.default.createDirectory(at: urlForVideoUrl, withIntermediateDirectories: true, attributes: nil)
                }catch {
                    
                }
                //创建文件地址
                let newVideoUrl = urlForVideoUrl.appendingPathComponent("\(videoFileName)", isDirectory: false)
                print("videwUrl == \(newVideoUrl)")
                VideoUtil.instance.compressVideo(fromurl: videoUrl, outputurl: newVideoUrl, finish: { (status) in
                    switch status {
                    case .failed:
                        print("failed")
                    case .unknown:
                        print("unknown")
                    case .waiting:
                        print("waiting")
                    case .exporting:
                        print("exporting")
                    case .completed:
                        //发送消息
                        let msg = ChatMessage(sessionId: self.sessionServerId, from: AppStatusManager.instance.userLoginStatus.1! , fromName: AppStatusManager.instance.userLoginStatus.2!, messageType: .video)
                        msg.videoPath = newVideoUrl.path
                        msg.avatar = AppStatusManager.instance.avatar
                        msg.me = 1
                        msg.messageType = .video
                        
                        //获取视频的宽高size
                        let videoSize = VideoUtil.instance.videoSizeAtPath(filePath: newVideoUrl.path)
                        //获取视频的时长
                        let videoTimeLength = VideoUtil.instance.videoDuration(filePath: newVideoUrl.path)
                        let thumbnailImage = VideoUtil.instance.getThumbnailImg(url: newVideoUrl)
                        print("videoSize == \(videoSize)")
                        print("videoTimeLength == \(Int64(videoTimeLength) * 1000)")
                        
                        
                        let thumbImagesize = thumbnailImage!.scaleImage(minSize: 60, maxSize: 120)
                        msg.videoWidth = thumbImagesize.width
                        msg.videoHeight = thumbImagesize.height
                        msg.videoThumbnail = thumbnailImage
                        //获取视频的内存大小
                        let size: Double = VideoUtil.instance.fileSizeAtPath(filePath: newVideoUrl.path)
                        //保留小数点后两位(M)
                        let finsize: Double = (size / 1024 / 1024).roundTo(places: 2)
                        /*
                         cotent:{"width":100,"height":100,"size":10,"duration":14389,"fileName":"fd07dbf870216d9dcf47ac4f63a8dded.mp4"}
                         duration:毫秒 size:M
                         */
                        let dic:[String:Any] = ["width": thumbImagesize.width, "height": thumbImagesize.height, "size": finsize, "duration": Int64(videoTimeLength) * 1000, "fileName": videoFileName]
                        let json = JSON(dic)
                        msg.text = json.rawString()
                        msg.fileName = videoFileName
                        //4.发送消息
                        self.sendMessage(sndMsg: msg)
//                        if let _ = try? FileManager.default.removeItem(at: videoUrl) {
//                            print("=======高清video删除成功")
//                        }
                    case .cancelled:
                        print("cancelled")
                    default:
                        print("other")
                    }
                })
            }
            
            
            
        default:
            print("Mismatched type: \(mediaType)")
        }
        
        picker.dismiss(animated: true, completion: nil)
    }
}

extension Double {
    //小数点后保留两位小数
    public func roundTo(places: Int) -> Double {
        let divisor = pow(10.0, Double(places))
        return (self * divisor).rounded() / divisor
    }
}
